package com.onpositive.wictionary.access;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;

import com.onpositive.nlp.inflector.English;

public class SemanticVocubalary implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	protected HashMap<String, VocubalaryEntry> vs = new HashMap<String, VocubalaryEntry>();

	protected HashMap<String, String> singleToPlural = new HashMap<String, String>();
	protected HashMap<String, String> pluralToSingle = new HashMap<String, String>();

	public void recordSinglePlural(String single, String plural) {
		singleToPlural.put(single, plural);
		pluralToSingle.put(plural, single);
	}

	public void add(VocubalaryEntry s) {
		s.synonims.remove(s.word);
		s.hypernims.remove(s.word);
		s.hyponims.remove(s.word);
		VocubalaryEntry vocubalaryEntry = vs.get(s);
		if (vocubalaryEntry != null) {
			vocubalaryEntry.hypernims.addAll(s.hypernims);
			vocubalaryEntry.hyponims.addAll(s.hyponims);
			vocubalaryEntry.synonims.addAll(s.synonims);
		} else {
			vs.put(s.word, s);
		}
		for (String q : s.synonims) {
			VocubalaryEntry vocubalaryEntry2 = vs.get(q);
			if (vocubalaryEntry2 == null) {
				vocubalaryEntry2 = new VocubalaryEntry(q);
				vs.put(q, vocubalaryEntry2);
			}
			vocubalaryEntry2.synonims.add(s.word);
		}
		for (String q : s.hypernims) {
			VocubalaryEntry vocubalaryEntry2 = vs.get(q);
			if (vocubalaryEntry2 == null) {
				vocubalaryEntry2 = new VocubalaryEntry(q);
				vs.put(q, vocubalaryEntry2);
			}
			vocubalaryEntry2.hyponims.add(s.word);
		}
		for (String q : s.hyponims) {
			VocubalaryEntry vocubalaryEntry2 = vs.get(q);
			if (vocubalaryEntry2 == null) {
				vocubalaryEntry2 = new VocubalaryEntry(q);
				vs.put(q, vocubalaryEntry2);
			}
			vocubalaryEntry2.hypernims.add(s.word);
		}
	}

	public int size() {
		return vs.size();
	}

	public boolean canBeUsedAsSubkind(String child, String parent) {
		child = child.replace('_', ' ');		
		parent = parent.replace('_', ' ');
		boolean internalMap = internalMap(child, parent);
		if (!internalMap) {
			if (parent.endsWith("s")) {
				internalMap = internalMap(child,
						parent.substring(0, parent.length() - 1));
				if (internalMap) {
					return true;
				}
			}
			String string = pluralToSingle.get(parent);
			if (string != null) {
				internalMap = internalMap(child, string);
				if (internalMap) {
					return true;
				}
			}
			string = singleToPlural.get(parent);
			if (string != null) {
				internalMap = internalMap(child, string);
				if (internalMap) {
					return true;
				}
			}
		}
		return internalMap;
	}

	protected boolean internalMap(String child, String parent) {
		if (parent.equals(child)){
			return false;
		}
		HashSet<String> ms = new HashSet<String>();
		boolean internalDo = internalDo(child, parent, ms, 0);
		if (!internalDo) {
			if (child.endsWith("s")) {
				boolean internalDo2 = internalDo(
						child.substring(0, child.length() - 1), parent,
						new HashSet<String>(), 0);
				if (internalDo2) {
					return internalDo2;
				}
			}
			boolean internalDo2 = internalDo(English.plural(child), parent,
					new HashSet<String>(), 0);
			if (!internalDo2) {
				String msa = singleToPlural.get(child);
				if (msa != null) {
					internalDo2 = internalDo(msa, parent,
							new HashSet<String>(), 0);
					if (internalDo2) {
						return internalDo2;
					}
				}
				msa = pluralToSingle.get(child);
				if (msa != null) {
					internalDo2 = internalDo(msa, parent,
							new HashSet<String>(), 0);
					if (internalDo2) {
						return internalDo2;
					}
				}
			}
			return internalDo2;
		}
		return internalDo;
	}

	protected boolean internalDo(String child, String parent,
			HashSet<String> ms, int sL) {
		if (child.equals(parent)) {
			return true;
		}
		VocubalaryEntry vocubalaryEntry = vs.get(child);
		if (ms.contains(child)) {
			return false;
		}
		ms.add(child);
		if (vocubalaryEntry != null) {
			if (vocubalaryEntry.hypernims.contains(parent)) {
				return true;
			}
			for (String s : vocubalaryEntry.hypernims) {
				if (internalDo(s, parent, ms, sL)) {
					return true;
				}
			}
			if (sL < 2) {
				for (String s : vocubalaryEntry.synonims) {
					if (internalDo(s, parent, ms, sL + 1)) {
						return true;
					}
				}
			}
		}
		return false;
	}
}
